
#ifndef __MY_UTIL__
#define __MY_UTIL__

#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
#include <memory>
#include <sstream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <jsoncpp/json/json.h>

namespace vod_ns
{
    class FileUtil
    {
    public:
        FileUtil(const std::string& name)
            : _name(name)
        {}

        // 判断文件是否存在 
        bool Exist()
        {
            // access 的 F_OK 专门用于检测文件是否存在 --> 存在返回 0，否则返回 -1 
            int ret = ::access(_name.c_str(), F_OK);
            if (ret != 0) 
            {
                std::cout << "The file does not exist, errno: " << errno << " -> " << strerror(errno) << std::endl;
                return false;
            }
            else return true;
        }

        // 文件大小 
        size_t Size()
        {
            if (!Exist()) return 0;
            // stat 用于获取文件属性 
            struct stat st;
            int ret = ::stat(_name.c_str(), &st);
            if (ret != 0)
            {
                std::cout << "Get file stat Error, errno: " << errno << " -> " << strerror(errno) << std::endl;
                return 0;
            }
            return st.st_size;
        }

        // 读取文件数据到 body 中 
        bool GetContent(std::string* body)
        {
            std::ifstream in;
            in.open(_name, std::ios::binary);
            if (in.is_open() == false)
            {
                std::cout << "open file(from) failed, errno: " << errno << " -> " << strerror(errno) << std::endl;
                return false;
            }
            size_t flen = Size();
            body->resize(flen);
            in.read(&((*body)[0]), flen);
            if (in.good() == false)
            {
                std::cout << "Read from file error, errno: " << errno << " -> " << strerror(errno) << std::endl;
                in.close();
                return false;
            }
            in.close();
            return true;
        }

        // 向文件写入数据 
        bool SetContent(const std::string& body)
        {
            std::ofstream out;
            out.open(_name, std::ios::binary);
            if (out.is_open() == false)
            {
                std::cout << "open file(into) failed, errno: " << errno << " -> " << strerror(errno) << std::endl;
                return false;
            }
            out.write(body.c_str(), body.size());
            if (out.good() == false)
            {
                std::cout << "Write into file error, errno: " << errno << " -> " << strerror(errno) << std::endl;
                out.close();
                return false;
            }
            out.close();
            return true;
        }

        // 针对目录时创建目录 
        bool CreateDirectory()
        {
            if (Exist()) return true;
            int ret = ::mkdir(_name.c_str(), 0777);
            if (ret != 0)
            {
                std::cout << "mkdir Error, errno: " << errno << " -> " << strerror(errno) << std::endl;
                return false;
            }
            return true;
        }

        ~FileUtil()
        {}

    private:
        std::string _name; // 文件路径名称 
    };


    class JsonUtil
    {
    public:
        static bool Serialize(const Json::Value& value, std::string* body)
        {
            Json::StreamWriterBuilder swb;
            std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());
            std::stringstream ss;
            int ret = sw->write(value, &ss);
            if (ret != 0)
            {
                std::cout << "Serialize Error, errno: " << errno << " -> " << strerror(errno) << std::endl;
                return false;
            }
            *body = ss.str();
            return true;
        }

        static bool Deserialize(const std::string& body, Json::Value* pvalue)
        {
            Json::CharReaderBuilder crb;
            std::unique_ptr<Json::CharReader> cr(crb.newCharReader());
            std::string err;
            bool ret = cr->parse(body.c_str(), body.c_str() + body.size(), pvalue, &err);
            if (ret == false)
            {
                std::cout << "Deserialize Error: " << err << std::endl;
                return false;
            }
            return true;
        }

    };
}

#endif